package com.wish.group05.finance.controller;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.io.IOException;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.wish.group05.base.entity.*;
import com.wish.group05.base.service.*;
import com.wish.group05.common.security.service.TokenService;
import com.wish.group05.finance.dto.CwClearingDto;
import com.wish.group05.system.api.model.LoginUser;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.weaver.loadtime.Aj;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import com.wish.group05.common.log.annotation.Log;
import com.wish.group05.common.log.enums.BusinessType;
import com.wish.group05.common.security.annotation.PreAuthorize;
import com.wish.group05.common.core.web.controller.BaseController;
import com.wish.group05.common.core.web.domain.AjaxResult;
import com.wish.group05.common.core.utils.poi.ExcelUtil;
import com.wish.group05.common.core.web.page.TableDataInfo;

/**
 * 结算Controller
 * 
 * @author wish
 * @date 2022-06-01
 */
@RestController
@RequestMapping("/clearing")
public class TCwClearingController extends BaseController
{
    @Autowired
    ICwClearingService cwClearingService;
    @Autowired
    ICwPayOrderDetailService cwPayOrderDetailService;
    @Autowired
    TokenService tokenService;
    @Autowired
    private IMCompanyAccountService companyAccountService;
    @Autowired
    ICwBalanceService cwBalanceService;
    @Autowired
    ICwCztxApplyService cwCztxApplyService;
    @Autowired
    ICwPayOrderService cwPayOrderService;

    /**
     * 确认结算
     * @param
     * @return
     */
    @GetMapping("/confirmSettlement/{ids}")
    public AjaxResult confirmSettlement(@PathVariable("ids")String ids) {
        CwClearingDto cwClearingDto = new CwClearingDto();
        List<Long> list=null;
        if (ids != null) {
            List<Long> collect = Arrays.asList(ids.split(",")).stream().map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
            System.out.println(collect);
            cwClearingDto.setClearingIds(collect);
            confirmClearing(cwClearingDto);
            return AjaxResult.success();
        }

        return AjaxResult.error("请选择一条记录");

    }

    /**
     * 确认结算处理 (结算确认以后，商户账户入账)
     * @param cwClearingDto
     */
    private void confirmClearing(CwClearingDto cwClearingDto) {
        logger.info("confirmClearing确认结算处理 Start...");

        if (cwClearingDto == null
        || cwClearingDto.getClearingIds()==null || cwClearingDto.getClearingIds().size()==0) {
            logger.warn("----结算对象数据无。");
            return;
        }

        // 取得需要结算的记录ID
        List<Long> clearingIdList = cwClearingDto.getClearingIds();
        logger.warn("----结算对象数据共{}条。", clearingIdList.size());

        // 循环处理每一个结算记录
        for (Long clearingItemId : clearingIdList) {
            logger.info("--------当前处理结算ID：{}", clearingItemId);

            // 1、************ 获取对应结算记录
            CwClearing clearing = cwClearingService.getById(clearingItemId);

            if (clearing == null || StringUtils.isBlank(clearing.getPayOrderNo())) {
                logger.warn("--------结算记录查询无。");
                continue;
            }

            // 2、************ 根据结算记录中的支付订单号查询对应的支付订单明细，
            //    并且进行业务订单金额的商户入账更新操作
            CwPayOrderDetail orderDetail = new CwPayOrderDetail();
            // 支付订单No
            orderDetail.setPayOrderNo(clearing.getPayOrderNo());
            orderDetail.setDelFlg(false);
            QueryWrapper<CwPayOrderDetail> wrapper = new QueryWrapper<>(orderDetail);
            List<CwPayOrderDetail> orderDetailList = cwPayOrderDetailService.list(wrapper);

            if (orderDetailList == null || orderDetailList.size() == 0) {
                logger.warn("--------该结算记录对应的支付订单流水明细查询无。");
                continue;
            }
            for (CwPayOrderDetail orderDetail1 : orderDetailList) {
                // add by fl 20180524 增加金融服务的场景 start
                if (orderDetail1.getCanClearingAmount() == null ||
                        orderDetail1.getCanClearingAmount() .equals(0)) {
                    // 商户可结算金额为空或者=0的时候，无需结算
                    logger.debug("--------该明细无商户可结算金额，无需结算，处理跳过。");
                    continue;
                }

                // add by fl 20180524 增加金融服务的场景 end
                // 2-1、企业账户更新（结算入账处理，包括企业账户流水的结算状态更新）
                this.updateBalanceInConfirmClearing(orderDetail1);
                logger.debug("--------企业账户及账户流水明细更新完成。");
                // 2-2、更新对应的业务订单状态(充值提现申请表和收款计划表)
                this.updateBusinessOrderInConfirmClearing(orderDetail1);
                logger.debug("--------业务订单状态更新完成。");
            }

            // 3、************ 更新对应的支付订单信息状态为已结算
            this.updatePayOrderInConfirmClearing(orderDetailList.get(0).getPayOrderId());

            logger.debug("--------支付订单结算状态更新完成。");


            // 4、************ 更新选中的结算记录的结算状态(从未确认更改为已确认)
            CwClearing cwClearingForUpdate = new CwClearing();
            cwClearingForUpdate.setId(clearingItemId);
            // 结算确认状态（2：已确认）
            cwClearingForUpdate.setClearingConfirmState(2);
            // 结算确认人
            cwClearingForUpdate.setClearingConfirmUserId(this.getLoginUser().getUserid());
            // 结算确认时间
            cwClearingForUpdate.setClearingConfirmDate(new Date());

            cwClearingForUpdate.setUpdateUserid(this.getLoginUser().getUserid());
            cwClearingForUpdate.setUpdateTime(new Date());

            //更新结算表
            cwClearingService.saveOrUpdate(cwClearingForUpdate);

            logger.debug("--------结算表更新完成。");
        }
        logger.info("confirmClearing确认结算处理 End.");
    }

    /**
     * 结算确认的时候，更新对应的支付订单信息状态为已结算
     * @param payOrderId
     */
    private void updatePayOrderInConfirmClearing(Long payOrderId) {

        logger.info("updatePayOrderInConfirmClearing结算确认的时候，更新对应的支付订单信息状态为已结算处理 Start...");

        CwPayOrder updateEntity = new CwPayOrder();
        updateEntity.setId(payOrderId);
        // 对账状态：已结算
        updateEntity.setDzState(4);


        updateEntity.setUpdateUserid(this.getLoginUser().getUserid());
        updateEntity.setUpdateTime(new Date());

        // 更新支付订单表
        cwPayOrderService.updateById(updateEntity);

        logger.info("updatePayOrderInConfirmClearing结算确认的时候，更新对应的支付订单信息状态为已结算处理 End.");
    }


    /**
     * 结算确认的时候，更新对应的业务订单状态(充值提现申请表和收款计划表)
     * @param orderDetail
     */
    private void updateBusinessOrderInConfirmClearing(CwPayOrderDetail orderDetail) {

        logger.info("updateBusinessOrderInConfirmClearing结算确认的时候，更新对应的业务订单状态处理 Start...");

        // 充值的时候，更新充值申请
        if (orderDetail.getBusinessOrderType() == 1) {
            CwCztxApply updateEntity = new CwCztxApply();
            updateEntity.setId(orderDetail.getBusinessOrderPlanId());
            // 到账时间（提现的时候到账时间，充值的时候结算到账时间）
            updateEntity.setDzDate(new Date());

            updateEntity.setUpdateUserid(this.getLoginUser().getUserid());
            updateEntity.setUpdateTime(new Date());

            // 更新充值提现申请信息表
            cwCztxApplyService.saveOrUpdate(updateEntity);

            logger.info("----更新数据({}).", JSON.toJSONString(updateEntity));

        }else if (orderDetail.getBusinessOrderType()==3){//收款状态
            // 收款的时候，更新对应收款计划状态
            // --------------- 收款计划中暂时无状态更新 ---------------

        }
        logger.info("updateBusinessOrderInConfirmClearing结算确认的时候，更新对应的业务订单状态处理 End.");
    }

    /**
     * 结算确认的时候，企业账户更新（结算入账处理）
     * @param orderDetail
     */
    private void updateBalanceInConfirmClearing(CwPayOrderDetail orderDetail) {
        logger.info("updateBalanceInConfirmClearing结算确认的时候，企业账户更新处理 Start...");
        // 目前业务中，入金的业务包括企业充值和企业收款即租客支付费用（金融相关业务的结算在前面已经过滤了一遍，都这里的理论上都是需要结算的费用）
        logger.info("----请求参数：{}", JSON.toJSONString(orderDetail));

        if (orderDetail.getBusinessOrderType() == 1) {
            // 入账金额
            BigDecimal confirmAmount = orderDetail.getBusinessOrderAmount();

            // 1、恢复企业的可提现余额，减少对应的冻结金额
            // 1-1、查询商户账号信息
            MCompanyAccount companyAccount = new MCompanyAccount();
            companyAccount.setBusinessId(orderDetail.getBusinessId());
            companyAccount.setDelFlg(false);

            QueryWrapper<MCompanyAccount> wrapper = new QueryWrapper<>(companyAccount);

            if (wrapper == null) {
                logger.error("----当前商户的企业账户信息查询不存在，商户账户更新跳过。商户ID：{}", orderDetail.getBusinessId());
                return;
            }

            // 1-2、更新商户账户余额
            MCompanyAccount mCompanyAccount = new MCompanyAccount();
            mCompanyAccount.setId(companyAccount.getId());
            // 可用余额
            mCompanyAccount.setCashableAmount(this.amountSum(companyAccount.getCashableAmount(),confirmAmount));
            // 冻结余额（不可使用余额）
            mCompanyAccount.setFrozenAmount(this.amountSub(companyAccount.getFrozenAmount(),confirmAmount));

            mCompanyAccount.setUpdateUserid(getLoginUser().getUserid());
            mCompanyAccount.setUpdateTime(new Date());
            // 更新商户账户余额信息
            this.companyAccountService.updateById(mCompanyAccount);
            logger.info("----更新商户账户余额完成，更新数据({}).", JSON.toJSONString(mCompanyAccount));

            // 2、更新该笔企业账户流水对应的结算状态(balance表)
            if (orderDetail.getBusinessOrderType() == 3) {
                // 目前充值只有成功未成功的状态，没有管理结算状态。  租客交费有结算状态，故业务收款的时候，需要更新账户流水状态

                // 2-1、查询对应的账户明细流水记录
                // 查询商户账号信息
                CwBalance cwBalanceOption = new CwBalance();
                //商户id
                cwBalanceOption.setBusinessId(orderDetail.getBusinessId());
                // 收支类型：收入
                cwBalanceOption.setBalanceType(1);
                // 操作类型：收款
                cwBalanceOption.setOperationType(3);
                // 业务订单ID
                cwBalanceOption.setYwOrderId(orderDetail.getBusinessOrderPlanId());
                cwBalanceOption.setDelFlg(false);
                QueryWrapper<CwBalance> queryWrapper = new QueryWrapper<>(cwBalanceOption);

                CwBalance cwBalanceEntity = cwBalanceService.getOne(queryWrapper);

                if (cwBalanceEntity == null) {
                    logger.error("----当前结算审核数据对应的企业账户Balance明细信息查询不存在，商户账户明细更新跳过。查询条件：{}", JSON.toJSONString(cwBalanceOption));
                    return;
                }

                // 2-2、企业账户明细更新
                CwBalance cwBalanceForUpdate = new CwBalance();
                cwBalanceForUpdate.setId(cwBalanceEntity.getId());
                cwBalanceForUpdate.setStatusCode(4);//已结算
                cwBalanceForUpdate.setStatusName("已结算");

                cwBalanceForUpdate.setUpdateUserid(this.getLoginUser().getUserid());
                cwBalanceForUpdate.setUpdateTime(new Date());

                cwBalanceService.saveOrUpdate(cwBalanceForUpdate);

                logger.info("----更新企业账户Balance明细完成，更新数据({}).", JSON.toJSONString(cwBalanceForUpdate));


            }

            logger.info("updateBalanceInConfirmClearing结算确认的时候，企业账户更新处理 End.");
        }
    }

    public LoginUser getLoginUser() {
        return tokenService.getLoginUser();
    }

    private BigDecimal amountSub(BigDecimal obj1, BigDecimal obj2) {

        if (obj1 == null) {
            return BigDecimal.ZERO;
        }

        if (obj2 == null) {
            return obj1;
        } else {
            BigDecimal subResult = obj1.subtract(obj2);
            if (subResult.compareTo(BigDecimal.ZERO) < 0) {
                return BigDecimal.ZERO;
            } else {
                return subResult;
            }
        }
    }

    private BigDecimal amountSum(BigDecimal obj1, BigDecimal obj2) {
        if (obj1 == null && obj2 == null) return BigDecimal.ZERO;
        if (obj1 == null) {
            return obj2;
        } else if (obj2 == null) {
            return obj1;
        } else {
            return obj1.add(obj2);
        }
    }

    /**
     * 查询结算列表
     */
    @PreAuthorize(hasPermi = "finance:clearing:clearinglist")
    @GetMapping("/list")
    public TableDataInfo list(CwClearing cwClearing)
    {
        //根据结算状态为未确认，删除状态为未删除的来查询
        QueryWrapper<CwClearing> wrapper = new QueryWrapper<>();
        if (StringUtils.isNoneBlank(cwClearing.getCheckBatchNo())) {
            wrapper.like("check_batch_no",cwClearing.getCheckBatchNo());
        }
        wrapper.eq("del_flg",0);
        wrapper.eq("clearing_confirm_state",1);
        startPage();
        List<CwClearing> list = cwClearingService.list(wrapper);
        return getDataTable(list);
    }

//   /* *//**
//     * 导出结算列表
//     *//*
//    @PreAuthorize(hasPermi = "system:clearing:export")
//    @Log(title = "结算", businessType = BusinessType.EXPORT)
//    @PostMapping("/export")
//    public void export(HttpServletResponse response, TCwClearing tCwClearing) throws IOException
//    {
//        List<TCwClearing> list = tCwClearingService.selectTCwClearingList(tCwClearing);
//        ExcelUtil<TCwClearing> util = new ExcelUtil<TCwClearing>(TCwClearing.class);
//        util.exportExcel(response, list, "clearing");
//    }
//
//    *//**
//     * 获取结算详细信息
//     *//*
//    @PreAuthorize(hasPermi = "system:clearing:query")
//    @GetMapping(value = "/{id}")
//    public AjaxResult getInfo(@PathVariable("id") Long id)
//    {
//        return AjaxResult.success(tCwClearingService.selectTCwClearingById(id));
//    }
//
//    *//**
//     * 新增结算
//     *//*
//    @PreAuthorize(hasPermi = "system:clearing:add")
//    @Log(title = "结算", businessType = BusinessType.INSERT)
//    @PostMapping
//    public AjaxResult add(@RequestBody TCwClearing tCwClearing)
//    {
//        return toAjax(tCwClearingService.insertTCwClearing(tCwClearing));
//    }
//
//    *//**
//     * 修改结算
//     *//*
//    @PreAuthorize(hasPermi = "system:clearing:edit")
//    @Log(title = "结算", businessType = BusinessType.UPDATE)
//    @PutMapping
//    public AjaxResult edit(@RequestBody TCwClearing tCwClearing)
//    {
//        return toAjax(tCwClearingService.updateTCwClearing(tCwClearing));
//    }
//
//    *//**
//     * 删除结算
//     *//*
//    @PreAuthorize(hasPermi = "system:clearing:remove")
//    @Log(title = "结算", businessType = BusinessType.DELETE)
//	@DeleteMapping("/{ids}")
//    public AjaxResult remove(@PathVariable Long[] ids)
//    {
//        return toAjax(tCwClearingService.deleteTCwClearingByIds(ids));
//    }*/
}
